home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C
/
Frameworks
/
Recursive Shell 1.0.1
/
Examples
/
ListFiles ƒ
/
GetFolder.c
< prev
next >
Wrap
Text File
|
1996-06-14
|
7KB
|
241 lines
/*****************************************************************************/
//
// GetFolder.c
//
// This source code displays the standard file dialog box, modified to allow
// the user to select a folder instead of a file.
// Code provided by Andrew Duncan.
//
// Version 1.0
//
// Created: 13 May 1996
// Modified: 14 June 1996
//
/*****************************************************************************/
#define CustomGetFolderDialogID 129
#define kSelectItem 13
#define kCanSelectDesktop false
#include "GetFolder.h"
//
// SameFile
//
static Boolean SameFile(FSSpec *spec1, FSSpec *spec2)
{
return ( (spec1->vRefNum == spec2->vRefNum)
&& (spec1->parID == spec2->parID)
&& (EqualString( spec1->name, spec2->name, false, true)) );
}
//
// AppendStrToStr
//
static void AppendStrToStr(StringPtr dst, StringPtr src, unsigned char maxDstLen)
{
short offset = dst[0]+1;
short size = src[0];
if ( dst[0] + src[0] > maxDstLen) size = maxDstLen - dst[0];
BlockMove( src+1, dst+offset, size);
dst[0] += size;
}
static FSSpec gDeskFolderSpec;
//
// SetSelectButtonName
//
// Gets the "Select" button from the CustomGetFile dialog and
// the filename string from the FSSpec parameter. It set the buttons name
// to Select “filename”, truncating the filemane if needed. The button is
// dimmed if kCanSelectDesktop==false and the FSSpec=the desktop folder.
//
static void SetSelectButtonName ( FSSpec *spec, DialogPtr theDlg )
{
Str255 btnName = "\p";
Str255 selectString = "\pSelect"; // Should really be a resource...
Str63 desktopFName = "\pDesktop"; // Ditto.
Str63 selNameTrunc = "\p";
Rect iRect;
Handle iHndl;
short btnWidth;
short iType;
Boolean hilited = true;
if (SameFile(spec, &gDeskFolderSpec))
{
AppendStrToStr(selNameTrunc, desktopFName, 63) ;
hilited = kCanSelectDesktop;
}
else
AppendStrToStr(selNameTrunc, spec->name, 63) ;
GetDItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
/* truncate select name to fit in button */
btnWidth = iRect.right - iRect.left;
btnWidth -= StringWidth(selectString);
btnWidth -= StringWidth("\p “” ");
TruncString(btnWidth, selNameTrunc, smTruncMiddle);
/* build button name string */
AppendStrToStr(btnName, selectString, 255) ;
AppendStrToStr(btnName, "\p “", 255) ;
AppendStrToStr(btnName, selNameTrunc, 255) ;
AppendStrToStr(btnName, "\p”", 255) ;
SetCTitle((ControlRef)iHndl, btnName);
if (hilited)
HiliteControl((ControlRef)iHndl,0);
else
HiliteControl((ControlRef)iHndl,255);
}
//
// MyDlgHook
//
static pascal short MyDlgHook ( short item, DialogPtr theDlg, void* userData )
{
StandardFileReply* reply;
FSSpec curSpec;
OSType refCon;
static FSSpec lastSpec; /* Remember lastSpec so that we don't update Select button needlessly */
OSErr err;
refCon = GetWRefCon(theDlg);
if (refCon != sfMainDialogRefCon)
return item;
reply = (StandardFileReply*) userData;
if (item == sfHookFirstCall) /* if the dialog is just about to appear */
lastSpec.vRefNum = -9999; /* init to ridiculous value */
if (item == sfHookNullEvent) /* if we got a NullEvent */
{
if ( !SameFile( &(reply->sfFile), &lastSpec) )
{
curSpec = reply->sfFile;
err = FSMakeFSSpec(curSpec.vRefNum, curSpec.parID, curSpec.name, &curSpec);
// MakeCanonFSSpec(&curSpec);
SetSelectButtonName(&curSpec, theDlg);
lastSpec = reply->sfFile ;
}
}
if (item == kSelectItem) item = sfItemOpenButton;
return item;
}
//
// MyFilterAllFiles
//
// A file filter proc that removes everything but directories from the
// CustomGetFile list. This means that only Folders, Volumes, or Aliases of
// Folders or Volumes will appear in the list.
//
static pascal Boolean MyFilterAllFiles(CInfoPBPtr pb, void* /*myDataPtr*/)
{
if (pb->hFileInfo.ioFlAttrib & (1 << 4)) /* file is a directory */
return false;
return true;
}
//
// CustomGetFolder
//
OSErr CustomGetFolder(StandardFileReply *reply)
{
Point where = {-1,-1}; /* center dialog on main screen */
OSErr err;
Boolean targetIsFolder,wasAliased;
FileFilterYDUPP ffUPP;
DlgHookYDUPP dhUPP;
err = FindFolder(kOnSystemDisk,
kDesktopFolderType,
kDontCreateFolder,
&gDeskFolderSpec.vRefNum,
&gDeskFolderSpec.parID);
gDeskFolderSpec.name[0] = '\0';
err = FSMakeFSSpec(gDeskFolderSpec.vRefNum, gDeskFolderSpec.parID, gDeskFolderSpec.name, &gDeskFolderSpec);
ffUPP = NewFileFilterYDProc(MyFilterAllFiles);
dhUPP = NewDlgHookYDProc(MyDlgHook);
CustomGetFile( ffUPP, /* file filter proc */
-1, /* number of file types */
nil, /* array of file types */
reply, /* the StandardFileReply structure */
CustomGetFolderDialogID, /* the dialog's ID */
where, /* position of dialog on screen */
dhUPP, /* the Dialog Hook procedure */
nil, /* no modal dialog filterProc */
nil, /* no activeListPtr */
nil, /* no activateProc */
reply /* yourDataPtr: pass reply in so that */
); /* MyDlgHook() can access current info */
if ( !reply->sfGood ) /* if the user hit cancel button */
return noErr ; /* then nothing more to do so return */
// If we were inside a folder with no subfolders, reply->sfFile.parID will be the
// ID of the folder (not that of its parent) and the string will be null. In that
// case, don’t try to resolve the alias.
if (reply->sfFile.name[0] != '\0')
{
err = ResolveAliasFile( &(reply->sfFile), true, &targetIsFolder, &wasAliased);
if (err) return err ;
}
// If is not a directory or volume (e.g. we were inside a folder with no subfolders.
if ( !reply->sfIsFolder && !reply->sfIsVolume )
{
FSSpec tempSpec;
CInfoPBRec infoPB;
Boolean IsDirectory;
tempSpec = reply->sfFile;
if (tempSpec.name[0] != '\0') return; //err
infoPB.dirInfo.ioNamePtr = tempSpec.name;
infoPB.dirInfo.ioVRefNum = tempSpec.vRefNum;
infoPB.dirInfo.ioDrDirID = tempSpec.parID;
infoPB.dirInfo.ioFDirIndex = -1;
err = PBGetCatInfo( &infoPB, false );
if (err) return err ;
tempSpec.parID = infoPB.dirInfo.ioDrParID ;
// make sure that it's a directory
IsDirectory = (infoPB.dirInfo.ioFlAttrib & 0x10) ;
if ( !IsDirectory ) return; //err
reply->sfFile = tempSpec ;
reply->sfScript = infoPB.dirInfo.ioDrFndrInfo.frScript ;
reply->sfFlags = infoPB.dirInfo.ioDrUsrWds.frFlags ;
reply->sfIsFolder = (tempSpec.parID == 1) ? (0x00) : (0xFF) ;
reply->sfIsVolume = (tempSpec.parID == 1) ? (0xFF) : (0x00) ; ;
}
return noErr;
}